// Copyright (C) ZHENG Zhong <heavyzheng nospam-at gmail D0T com>
//
// $Id: to_str.hpp 224 2008-09-08 11:55:49Z heavyzheng $
//

#ifndef ZZHENG_LOGGING_TO_STR_HPP_20080905__
#define ZZHENG_LOGGING_TO_STR_HPP_20080905__

#include <zzheng/logging/config.hpp>

#ifdef ZZHENG_MSVC
#  pragma warning(push)
#  pragma warning(disable: 4127 4511 4512)
#endif // ZZHENG_MSVC

#include <boost/lexical_cast.hpp>
#include <boost/format.hpp>

#ifdef ZZHENG_MSVC
#  pragma warning(pop)
#endif // ZZHENG_MSVC

#include <exception>
#include <typeinfo>
#include <string>
#include <utility>
#include <functional>

namespace zzheng {
namespace logging {
namespace detail {

    //! Function object class template to convert a value of type T to a string.
    template<typename T>
    struct value_to_str: public std::unary_function<T, std::string> {
        result_type operator()(const argument_type& value) const {
            return boost::lexical_cast<std::string>(value);
        }
    }; // struct value_to_str<T>

    //! Specialization of class template value_to_str for std::string.
    template<>
    struct value_to_str<std::string>: public std::unary_function<std::string, std::string> {
        result_type operator()(const argument_type& value) const {
            return ( "\"" + value + "\"" );
        }
    }; // struct value_to_str<std::string>

    //! Specialization of class template value_to_str for const char*.
    template<>
    struct value_to_str<const char*>: public std::unary_function<const char*, std::string> {
        result_type operator()(const argument_type& value) const {
            std::string value_str = (value != 0 ? std::string(value) : "<null>");
            return ( "\"" + value_str + "\"" );
        }
    }; // struct value_to_str<const char*>

    //! Specialization of class template value_to_str for const char*.
    template<>
    struct value_to_str<char*>: public std::unary_function<char*, std::string> {
        result_type operator()(const argument_type& value) const {
            std::string value_str = (value != 0 ? std::string(value) : "<null>");
            return ( "\"" + value_str + "\"" );
        }
    }; // struct value_to_str<char*>

    //! Partial specialization of class template value_to_str for std::pair<T, U>.
    template<typename T, typename U>
    struct value_to_str<std::pair<T, U> >
    : public std::unary_function<std::pair<T, U>, std::string> {

        std::string operator()(const std::pair<T, U>& pair) const {
            value_to_str<T> t_to_str;
            value_to_str<U> u_to_str;
            return ( "(" + t_to_str(pair.first) + "," + u_to_str(pair.second) + ")" );
        }

    }; // struct value_to_str<std::pair<T, U> >

    ////////////////////////////////////////////////////////////////////////////////////////////////

    //! Converts an exception to a string. The string includes the type info of the exception and
    //! the message carried in the exception.
    //! \param ex  the exception to convert to string.
    //! \return the string representation of the exception.
    inline
    std::string exception_to_str(const std::exception& ex) {
        std::string str;
        str.append("(exception: ").append(typeid(ex).name()).append("): ").append(ex.what());
        return str;
    }

    //! Converts a type_info and a raw address to a string.
    //! \tparam T 
    //! \param type  the type_info to convert to string.
    //! \param addr  the raw address to convert to string.
    //! \return the string representation of the type_info and the raw address.
    template<typename T>
    inline
    std::string ptr_to_str(T* ptr) {
        return boost::str( boost::format("@0x%p(%s)")
                         % static_cast<const void*>(ptr)
                         % typeid(*ptr).name() );
    }

} // namespace zzheng::logging::detail
} // namespace zzheng::logging
} // namespace zzheng

#endif // ZZHENG_LOGGING_TO_STR_HPP_20080905__



